//go:build sql_integration

package datastore

import (
	"context"
	"fmt"
	"testing"

	namespaceDS "github.com/stackrox/rox/central/namespace/datastore"
	"github.com/stackrox/rox/central/vulnmgmt/vulnerabilityrequest/cache"
	"github.com/stackrox/rox/central/vulnmgmt/vulnerabilityrequest/common"
	"github.com/stackrox/rox/central/vulnmgmt/vulnerabilityrequest/datastore/internal/store/postgres"
	"github.com/stackrox/rox/generated/storage"
	"github.com/stackrox/rox/pkg/fixtures"
	"github.com/stackrox/rox/pkg/grpc/authn"
	mockIdentity "github.com/stackrox/rox/pkg/grpc/authn/mocks"
	"github.com/stackrox/rox/pkg/postgres/pgtest"
	"github.com/stackrox/rox/pkg/protoassert"
	"github.com/stackrox/rox/pkg/protocompat"
	"github.com/stackrox/rox/pkg/sac"
	"github.com/stackrox/rox/pkg/sac/resources"
	"github.com/stackrox/rox/pkg/uuid"
	"github.com/stretchr/testify/suite"
	"go.uber.org/mock/gomock"
)

// SAC contexts are defined in datastore_impl_test.go
var (
	noVMAccessSac = sac.WithGlobalAccessScopeChecker(context.Background(),
		sac.AllowFixedScopes(
			sac.AccessModeScopeKeys(storage.Access_READ_ACCESS),
			sac.ResourceScopeKeys(resources.Alert)))
	requesterReadSac = sac.WithGlobalAccessScopeChecker(context.Background(),
		sac.AllowFixedScopes(
			sac.AccessModeScopeKeys(storage.Access_READ_ACCESS),
			sac.ResourceScopeKeys(resources.VulnerabilityManagementRequests)))
	requesterWriteSac = sac.WithGlobalAccessScopeChecker(context.Background(),
		sac.AllowFixedScopes(
			sac.AccessModeScopeKeys(storage.Access_READ_WRITE_ACCESS),
			sac.ResourceScopeKeys(resources.VulnerabilityManagementRequests)))
	requesterAllSac = sac.WithGlobalAccessScopeChecker(context.Background(),
		sac.AllowFixedScopes(
			sac.AccessModeScopeKeys(storage.Access_READ_ACCESS, storage.Access_READ_WRITE_ACCESS),
			sac.ResourceScopeKeys(resources.VulnerabilityManagementRequests)))
	approverReadSac = sac.WithGlobalAccessScopeChecker(context.Background(),
		sac.AllowFixedScopes(
			sac.AccessModeScopeKeys(storage.Access_READ_ACCESS),
			sac.ResourceScopeKeys(resources.VulnerabilityManagementApprovals)))
	approverWriteSac = sac.WithGlobalAccessScopeChecker(context.Background(),
		sac.AllowFixedScopes(
			sac.AccessModeScopeKeys(storage.Access_READ_WRITE_ACCESS),
			sac.ResourceScopeKeys(resources.VulnerabilityManagementApprovals)))
	approverAllSac = sac.WithGlobalAccessScopeChecker(context.Background(),
		sac.AllowFixedScopes(
			sac.AccessModeScopeKeys(storage.Access_READ_ACCESS, storage.Access_READ_WRITE_ACCESS),
			sac.ResourceScopeKeys(resources.VulnerabilityManagementApprovals)))
	selfApproverReadSac = sac.WithGlobalAccessScopeChecker(context.Background(),
		sac.AllowFixedScopes(
			sac.AccessModeScopeKeys(storage.Access_READ_ACCESS),
			sac.ResourceScopeKeys(resources.VulnerabilityManagementRequests, resources.VulnerabilityManagementApprovals)))
	selfApproverWriteSac = sac.WithGlobalAccessScopeChecker(context.Background(),
		sac.AllowFixedScopes(
			sac.AccessModeScopeKeys(storage.Access_READ_WRITE_ACCESS),
			sac.ResourceScopeKeys(resources.VulnerabilityManagementRequests, resources.VulnerabilityManagementApprovals)))
	selfApproverAllSac = sac.WithGlobalAccessScopeChecker(context.Background(),
		sac.AllowFixedScopes(
			sac.AccessModeScopeKeys(storage.Access_READ_ACCESS, storage.Access_READ_WRITE_ACCESS),
			sac.ResourceScopeKeys(resources.VulnerabilityManagementRequests, resources.VulnerabilityManagementApprovals)))
)

const (
	approvedMessage = "approved"

	fakeUserID    = "user-id-a"
	altFakeUserID = "another users id"
)

func TestVulnRequestPostgresDataStore(t *testing.T) {
	suite.Run(t, new(VulnRequestPostgresDataStoreTestSuite))
}

func TestVulnRequestPostgresDataStoreUnifiedCVEDeferral(t *testing.T) {
	suite.Run(t, new(VulnRequestPostgresDataStoreTestSuite))
}

type VulnRequestPostgresDataStoreTestSuite struct {
	suite.Suite

	db      *pgtest.TestPostgres
	dbStore postgres.Store

	mockCtrl     *gomock.Controller
	mockIdentity *mockIdentity.MockIdentity
	altIdentity  *mockIdentity.MockIdentity

	datastore *datastoreImpl
}

func (s *VulnRequestPostgresDataStoreTestSuite) SetupSuite() {
	s.db = pgtest.ForT(s.T())
	s.dbStore = postgres.New(s.db)
	namespaceDatastore, err := namespaceDS.GetTestPostgresDataStore(s.T(), s.db.DB)
	s.Require().NoError(err)
	s.datastore = &datastoreImpl{
		store:              s.dbStore,
		pendingReqCache:    cache.New(),
		namespaceDatastore: namespaceDatastore,
	}
}

func (s *VulnRequestPostgresDataStoreTestSuite) SetupTest() {
	s.mockCtrl = gomock.NewController(s.T())

	ctx := sac.WithAllAccess(context.Background())
	var err error
	_, err = s.db.Exec(ctx, "TRUNCATE TABLE vulnerability_requests CASCADE")
	s.Require().NoError(err)
	_, err = s.db.Exec(ctx, "TRUNCATE TABLE vulnerability_requests_approvers CASCADE")
	s.Require().NoError(err)
	_, err = s.db.Exec(ctx, "TRUNCATE TABLE vulnerability_requests_comments CASCADE")
	s.Require().NoError(err)
	_, err = s.db.Exec(ctx, "TRUNCATE TABLE vulnerability_requests_approvers_v2 CASCADE")
	s.Require().NoError(err)
	s.datastore.pendingReqCache = cache.New()

	s.mockIdentity = mockIdentity.NewMockIdentity(s.mockCtrl)
	s.mockIdentity.EXPECT().UID().Return(fakeUserID).AnyTimes()
	s.mockIdentity.EXPECT().FullName().Return("First Last").AnyTimes()
	s.mockIdentity.EXPECT().FriendlyName().Return("DefinitelyNotBob").AnyTimes()
	s.altIdentity = mockIdentity.NewMockIdentity(s.mockCtrl)
	s.altIdentity.EXPECT().UID().Return(altFakeUserID).AnyTimes()
	s.altIdentity.EXPECT().FullName().Return("Last First").AnyTimes()
	s.altIdentity.EXPECT().FriendlyName().Return("DefinitelyNotJimmy").AnyTimes()
}

func (s *VulnRequestPostgresDataStoreTestSuite) TearDownTest() {
	s.mockCtrl.Finish()
}

func createPendingVulnerabilityRequest(id string) *storage.VulnerabilityRequest {
	return &storage.VulnerabilityRequest{
		Id:        id,
		Name:      fmt.Sprintf("Vulnerability Request %s", id),
		Requestor: &storage.SlimUser{Id: fakeUserID},
		Expired:   false,
	}
}

func createPendingDeferralVulnerabilityRequest(id string) *storage.VulnerabilityRequest {
	req := fixtures.GetGlobalDeferralRequestV2("cve-1", "cve-2")
	req.Id = id
	req.Name = fmt.Sprintf("Vulnerability Request %s", id)
	return req.CloneVT()
}

func createPendingDeferralUpdateVulnerabilityRequest(id string) *storage.VulnerabilityRequest {
	defUpdate := &storage.VulnerabilityRequest_DeferralUpdate{
		DeferralUpdate: &storage.DeferralUpdate{
			Expiry: &storage.RequestExpiry{
				Expiry: &storage.RequestExpiry_ExpiresOn{
					ExpiresOn: protocompat.TimestampNow(),
				},
			},
			CVEs: []string{"cve-1"},
		},
	}
	req := createPendingDeferralVulnerabilityRequest(id)
	req.UpdatedReq = defUpdate
	req.Status = storage.RequestStatus_APPROVED_PENDING_UPDATE
	return req.CloneVT()
}

func createPendingFalsePositiveVulnerabilityRequest(id string) *storage.VulnerabilityRequest {
	req := fixtures.GetGlobalFPRequestV2("cve-1", "cve-2").CloneVT()
	req.Id = id
	req.Name = fmt.Sprintf("Vulnerability Request %s", id)
	return req.CloneVT()
}

func createPendingFalsePositiveUpdateVulnerabilityRequest(id string) *storage.VulnerabilityRequest {
	req := createPendingFalsePositiveVulnerabilityRequest(id)
	fpUpdate := &storage.VulnerabilityRequest_FalsePositiveUpdate{
		FalsePositiveUpdate: &storage.FalsePositiveUpdate{
			CVEs: []string{"cve-1"},
		},
	}
	req.UpdatedReq = fpUpdate
	req.Status = storage.RequestStatus_APPROVED_PENDING_UPDATE
	return req.CloneVT()
}

func (s *VulnRequestPostgresDataStoreTestSuite) injectRequest(req *storage.VulnerabilityRequest) {
	err := s.datastore.AddRequest(selfApproverAllSac, req)
	s.Require().NoError(err)
}

func (s *VulnRequestPostgresDataStoreTestSuite) injectGeneratedRequest(id string) {
	req := createPendingVulnerabilityRequest(id)
	s.injectRequest(req)
}

func (s *VulnRequestPostgresDataStoreTestSuite) injectGeneratedExpiredRequest(id string) {
	req := createPendingVulnerabilityRequest(id)
	req.Expired = true
	s.injectRequest(req)
}

func copyDeferralUpdate(req *storage.VulnerabilityRequest) *storage.DeferralUpdate {
	return req.GetDeferralUpdate().CloneVT()
}

func copyFalsePositiveUpdate(req *storage.VulnerabilityRequest) *storage.FalsePositiveUpdate {
	return req.GetFalsePositiveUpdate().CloneVT()
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestCountRequiresReadOnAny() {
	var err error
	for _, ctx := range []context.Context{requesterReadSac, requesterAllSac, approverReadSac, approverAllSac, selfApproverReadSac, selfApproverAllSac} {
		count, err := s.datastore.Count(ctx, nil)
		s.Zero(count)
		s.NoError(err)
	}

	_, err = s.datastore.Count(noVMAccessSac, nil)
	s.ErrorIs(err, sac.ErrResourceAccessDenied)

	s.injectGeneratedRequest(uuid.NewTestUUID(101).String())
	for _, ctx := range []context.Context{requesterReadSac, requesterAllSac, approverReadSac, approverAllSac, selfApproverReadSac, selfApproverAllSac} {
		count, err := s.datastore.Count(ctx, nil)
		s.Equal(1, count)
		s.NoError(err)
	}

	_, err = s.datastore.Count(noVMAccessSac, nil)
	s.ErrorIs(err, sac.ErrResourceAccessDenied)
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestExistsRequiresReadOnAny() {
	existingID := uuid.NewTestUUID(201).String()
	missingID := uuid.NewTestUUID(202).String()
	s.injectGeneratedRequest(existingID)
	for _, ctx := range []context.Context{requesterReadSac, requesterAllSac, approverReadSac, approverAllSac, selfApproverReadSac, selfApproverAllSac} {
		exists, err := s.datastore.Exists(ctx, existingID)
		s.True(exists)
		s.NoError(err)
	}
	for _, ctx := range []context.Context{requesterReadSac, requesterAllSac, approverReadSac, approverAllSac, selfApproverReadSac, selfApproverAllSac} {
		exists, err := s.datastore.Exists(ctx, missingID)
		s.False(exists)
		s.NoError(err)
	}

	_, err := s.datastore.Exists(noVMAccessSac, existingID)
	s.ErrorIs(err, sac.ErrResourceAccessDenied)
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestGetRequiresReadOnAny() {
	existingRequestID := uuid.NewTestUUID(301).String()
	missingRequestID := uuid.NewTestUUID(302).String()
	existingRequest := createPendingVulnerabilityRequest(existingRequestID)
	s.injectRequest(existingRequest)
	for _, ctx := range []context.Context{requesterReadSac, requesterAllSac, approverReadSac, approverAllSac, selfApproverReadSac, selfApproverAllSac} {
		req, found, err := s.datastore.Get(ctx, existingRequestID)
		s.NoError(err)
		s.True(found)
		protoassert.Equal(s.T(), existingRequest, req)
	}
	for _, ctx := range []context.Context{requesterReadSac, requesterAllSac, approverReadSac, approverAllSac, selfApproverReadSac, selfApproverAllSac} {
		req, found, err := s.datastore.Get(ctx, missingRequestID)
		s.NoError(err)
		s.False(found)
		s.Nil(req)
	}

	var err error
	_, _, err = s.datastore.Get(noVMAccessSac, existingRequestID)
	s.ErrorIs(err, sac.ErrResourceAccessDenied)
	_, _, err = s.datastore.Get(noVMAccessSac, missingRequestID)
	s.ErrorIs(err, sac.ErrResourceAccessDenied)
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestGetManyRequiresReadOnAny() {
	existingID := uuid.NewTestUUID(401).String()
	missingID := uuid.NewTestUUID(402).String()
	existingRequest := createPendingVulnerabilityRequest(existingID)
	s.injectRequest(existingRequest)
	for _, ctx := range []context.Context{requesterReadSac, requesterAllSac, approverReadSac, approverAllSac, selfApproverReadSac, selfApproverAllSac} {
		fetched, err := s.datastore.GetMany(ctx, []string{existingID, missingID})
		s.NoError(err)
		protoassert.ElementsMatch(s.T(), []*storage.VulnerabilityRequest{existingRequest}, fetched)
	}

	_, err := s.datastore.GetMany(noVMAccessSac, []string{existingID, missingID})
	s.ErrorIs(err, sac.ErrResourceAccessDenied)
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestOnlyRequesterWithWriteCanAddRequest() {
	toAddRequests := []*storage.VulnerabilityRequest{
		createPendingVulnerabilityRequest(uuid.NewTestUUID(501).String()),
		createPendingVulnerabilityRequest(uuid.NewTestUUID(502).String()),
		createPendingVulnerabilityRequest(uuid.NewTestUUID(503).String()),
		createPendingVulnerabilityRequest(uuid.NewTestUUID(504).String()),
	}
	for ix, ctx := range []context.Context{requesterWriteSac, requesterAllSac, selfApproverWriteSac, selfApproverAllSac} {
		err := s.datastore.AddRequest(ctx, toAddRequests[ix])
		s.NoError(err)
	}

	toFailAddRequests := []*storage.VulnerabilityRequest{
		createPendingVulnerabilityRequest(uuid.NewTestUUID(511).String()),
		createPendingVulnerabilityRequest(uuid.NewTestUUID(512).String()),
		createPendingVulnerabilityRequest(uuid.NewTestUUID(513).String()),
		createPendingVulnerabilityRequest(uuid.NewTestUUID(514).String()),
		createPendingVulnerabilityRequest(uuid.NewTestUUID(515).String()),
		createPendingVulnerabilityRequest(uuid.NewTestUUID(516).String()),
	}
	for ix, ctx := range []context.Context{requesterReadSac, approverReadSac, approverWriteSac, approverAllSac, selfApproverReadSac, noVMAccessSac} {
		err := s.datastore.AddRequest(ctx, toFailAddRequests[ix])
		s.ErrorIs(err, sac.ErrResourceAccessDenied)
	}
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestOnlyApproversWithWriteCanUpdateStatus() {
	for ix, ctx := range []context.Context{approverWriteSac, approverAllSac, selfApproverWriteSac, selfApproverAllSac} {
		requestID := uuid.NewTestUUID(ix + 601).String()
		s.injectGeneratedRequest(requestID)
		updated, err := s.datastore.UpdateRequestStatus(ctx, requestID, approvedMessage, storage.RequestStatus_APPROVED)
		s.NoError(err)
		s.Require().NotNil(updated)
		s.Equal(updated.GetStatus(), storage.RequestStatus_APPROVED)
	}

	for ix, ctx := range []context.Context{requesterReadSac, requesterWriteSac, approverReadSac, selfApproverReadSac, noVMAccessSac} {
		requestID := uuid.NewTestUUID(ix + 611).String()
		s.injectGeneratedRequest(requestID)
		_, err := s.datastore.UpdateRequestStatus(ctx, requestID, approvedMessage, storage.RequestStatus_APPROVED)
		s.ErrorIs(err, sac.ErrResourceAccessDenied)
	}
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestUpdateStatusAddsApproversAndComments() {
	requestID := uuid.NewTestUUID(801).String()
	req := createPendingVulnerabilityRequest(requestID)
	s.injectRequest(req)
	resp, err := s.datastore.UpdateRequestStatus(
		authn.ContextWithIdentity(selfApproverAllSac, s.mockIdentity, s.T()),
		requestID,
		approvedMessage,
		storage.RequestStatus_APPROVED,
	)
	s.NoError(err)

	s.Len(resp.GetComments(), 1)
	s.Equal(resp.GetComments()[0].GetMessage(), approvedMessage)
	s.Equal(resp.GetComments()[0].GetUser().GetName(), s.mockIdentity.FullName())

	s.Len(resp.GetApprovers(), 1)
	s.Equal(resp.GetApprovers()[0].GetName(), s.mockIdentity.FullName())
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestCannotUpdateStatusToPending() {
	requestID := uuid.NewTestUUID(901).String()
	s.injectGeneratedRequest(requestID)
	_, err := s.datastore.UpdateRequestStatus(
		authn.ContextWithIdentity(selfApproverAllSac, s.mockIdentity, s.T()),
		requestID,
		approvedMessage,
		storage.RequestStatus_PENDING,
	)
	s.EqualError(err, "vulnerability request cannot be moved to pending state")
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestCannotUpdateStatusToApprovedPendingUpdate() {
	requestID := uuid.NewTestUUID(1001).String()
	s.injectGeneratedRequest(requestID)
	_, err := s.datastore.UpdateRequestStatus(
		authn.ContextWithIdentity(selfApproverAllSac, s.mockIdentity, s.T()),
		requestID,
		approvedMessage,
		storage.RequestStatus_APPROVED_PENDING_UPDATE,
	)
	s.EqualError(err, "vulnerability request cannot be moved to pending state")
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestUpdateStatusRequiresComment() {
	requestID := uuid.NewTestUUID(1101).String()
	s.injectGeneratedRequest(requestID)
	_, err := s.datastore.UpdateRequestStatus(
		authn.ContextWithIdentity(selfApproverAllSac, s.mockIdentity, s.T()),
		requestID,
		"",
		storage.RequestStatus_APPROVED,
	)
	s.EqualError(err, "comment is required when approving/denying a vulnerability request")
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestUpdateStatus_UnifiedCVEDeferral() {
	request1 := createPendingDeferralVulnerabilityRequest(uuid.NewTestUUID(1201).String())
	request2 := createPendingDeferralVulnerabilityRequest(uuid.NewTestUUID(1202).String())
	request3 := createPendingDeferralUpdateVulnerabilityRequest(uuid.NewTestUUID(1203).String())
	request4 := createPendingDeferralUpdateVulnerabilityRequest(uuid.NewTestUUID(1204).String())
	request5 := createPendingFalsePositiveUpdateVulnerabilityRequest(uuid.NewTestUUID(1205).String())

	cases := []struct {
		name                string
		existingReq         *storage.VulnerabilityRequest
		status              storage.RequestStatus
		expectedStatus      storage.RequestStatus
		expectedDeferralReq *storage.DeferralRequest
		expectedFpRequest   *storage.FalsePositiveRequest
		expectedCVEs        []string
	}{
		{
			name:                "Pending request should be approved",
			existingReq:         request1,
			status:              storage.RequestStatus_APPROVED,
			expectedStatus:      storage.RequestStatus_APPROVED,
			expectedDeferralReq: request1.GetDeferralReq().CloneVT(),
			expectedFpRequest:   request1.GetFpRequest().CloneVT(),
			expectedCVEs:        request1.GetCves().CloneVT().GetCves(),
		},
		{
			name:                "Pending request should be denied",
			existingReq:         request2,
			status:              storage.RequestStatus_DENIED,
			expectedStatus:      storage.RequestStatus_DENIED,
			expectedDeferralReq: request2.GetDeferralReq().CloneVT(),
			expectedFpRequest:   request2.GetFpRequest().CloneVT(),
			expectedCVEs:        request2.GetCves().CloneVT().GetCves(),
		},
		{
			name:                "Request pending update that was denied should go back to old approved state",
			existingReq:         request3,
			status:              storage.RequestStatus_DENIED,
			expectedStatus:      storage.RequestStatus_APPROVED,
			expectedDeferralReq: request3.GetDeferralReq().CloneVT(),
			expectedFpRequest:   request3.GetFpRequest().CloneVT(),
			expectedCVEs:        request3.GetCves().CloneVT().GetCves(),
		},
		{
			name:                "Deferral request pending update that was approved should have req and entities updated",
			existingReq:         request4,
			status:              storage.RequestStatus_APPROVED,
			expectedStatus:      storage.RequestStatus_APPROVED,
			expectedDeferralReq: &storage.DeferralRequest{Expiry: copyDeferralUpdate(request4).GetExpiry()},
			expectedFpRequest:   nil,
			expectedCVEs:        copyDeferralUpdate(request4).GetCVEs(),
		},
		{
			name:                "False positive request pending update that was approved should have req and entities updated",
			existingReq:         request5,
			status:              storage.RequestStatus_APPROVED,
			expectedStatus:      storage.RequestStatus_APPROVED,
			expectedDeferralReq: nil,
			expectedFpRequest:   &storage.FalsePositiveRequest{},
			expectedCVEs:        copyFalsePositiveUpdate(request5).GetCVEs(),
		},
	}

	for _, c := range cases {
		s.T().Run(c.name, func(t *testing.T) {
			s.injectRequest(c.existingReq)
			resp, err := s.datastore.UpdateRequestStatus(
				authn.ContextWithIdentity(selfApproverAllSac, s.mockIdentity, s.T()),
				c.existingReq.GetId(),
				"status changed",
				c.status,
			)
			s.NoError(err)
			s.Len(resp.GetComments(), 2)
			s.Equal("status changed", resp.GetComments()[1].GetMessage())
			s.Len(resp.GetApproversV2(), 1)
			s.Equal(resp.GetApproversV2()[0].GetName(), s.mockIdentity.FullName())
			s.Equal(c.expectedStatus, resp.GetStatus())
			protoassert.Equal(t, c.expectedDeferralReq, resp.GetDeferralReq())
			protoassert.Equal(t, c.expectedFpRequest, resp.GetFpRequest())
			s.Equal(c.expectedCVEs, resp.GetCves().GetCves())
		})
	}
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestUpdateRequestExpiryRequiresWriteOnAny() {
	expiry := &storage.RequestExpiry{Expiry: &storage.RequestExpiry_ExpiresWhenFixed{ExpiresWhenFixed: true}}
	req := fixtures.GetGlobalDeferralRequest("cve-a-b-c")
	req.Requestor = &storage.SlimUser{Id: fakeUserID}

	for ix, ctx := range []context.Context{requesterWriteSac, requesterAllSac, approverWriteSac, approverAllSac, selfApproverWriteSac, selfApproverAllSac} {
		testReq := req.CloneVT()
		testReq.Id = uuid.NewTestUUID(ix + 1301).String()
		testReq.Name = fmt.Sprintf("VulnerabilityRequest %s", testReq.GetId())
		s.injectRequest(testReq)
		_, err := s.datastore.UpdateRequestExpiry(
			authn.ContextWithIdentity(ctx, s.mockIdentity, s.T()),
			testReq.GetId(),
			"update comment",
			expiry,
		)
		s.NoError(err)
	}

	for ix, ctx := range []context.Context{requesterReadSac, approverReadSac, selfApproverReadSac, noVMAccessSac} {
		testReq := req.CloneVT()
		testReq.Id = uuid.NewTestUUID(ix + 1311).String()
		testReq.Name = fmt.Sprintf("VulnerabilityRequest %s", testReq.GetId())
		s.injectRequest(testReq)
		_, err := s.datastore.UpdateRequestExpiry(ctx, testReq.GetId(), "update comment", expiry)
		s.ErrorIs(err, sac.ErrResourceAccessDenied)
	}
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestRequesterCannotUpdateOthersRequestExpiry() {
	expiry := &storage.RequestExpiry{Expiry: &storage.RequestExpiry_ExpiresOn{ExpiresOn: protocompat.TimestampNow()}}
	for ix, ctx := range []context.Context{requesterWriteSac, requesterAllSac} {
		requestID := uuid.NewTestUUID(ix + 1401).String()
		s.injectGeneratedRequest(requestID)
		_, err := s.datastore.UpdateRequestExpiry(
			authn.ContextWithIdentity(ctx, s.altIdentity, s.T()),
			requestID,
			"comment",
			expiry,
		)
		s.ErrorIs(err, sac.ErrResourceAccessDenied)
	}
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestApproversCanUpdateOthersRequestExpiry() {
	expiry := &storage.RequestExpiry{Expiry: &storage.RequestExpiry_ExpiresWhenFixed{ExpiresWhenFixed: true}}
	req := fixtures.GetGlobalDeferralRequest("cve-a-b-c").CloneVT()
	req.Requestor = &storage.SlimUser{Id: "another users id"}

	for ix, ctx := range []context.Context{approverWriteSac, approverAllSac, selfApproverWriteSac, selfApproverAllSac} {
		requestID := uuid.NewTestUUID(ix + 1501).String()
		testReq := req.CloneVT()
		testReq.Id = requestID
		testReq.Name = fmt.Sprintf("Vulnerability Request %s", testReq.GetId())
		s.injectRequest(testReq)
		_, err := s.datastore.UpdateRequestExpiry(
			authn.ContextWithIdentity(ctx, s.mockIdentity, s.T()),
			requestID,
			"comment",
			expiry,
		)
		s.NoError(err)
	}
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestUpdateExpiryRequiresComment() {
	requestID := uuid.NewTestUUID(1601).String()
	s.injectGeneratedRequest(requestID)
	_, err := s.datastore.UpdateRequestExpiry(
		authn.ContextWithIdentity(selfApproverAllSac, s.mockIdentity, s.T()),
		requestID,
		"",
		&storage.RequestExpiry{Expiry: &storage.RequestExpiry_ExpiresWhenFixed{ExpiresWhenFixed: true}},
	)
	s.EqualError(err, "comment is required when updating a request's expiry")
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestUpdateRequestExpiryFailsINotDeferralRequest() {
	expiry := &storage.RequestExpiry{Expiry: &storage.RequestExpiry_ExpiresWhenFixed{ExpiresWhenFixed: true}}
	requestID := uuid.NewTestUUID(1701).String()
	req := fixtures.GetGlobalFPRequest("cve-a-b-c").CloneVT()
	req.Id = requestID
	req.Name = requestID
	s.injectRequest(req)

	_, err := s.datastore.UpdateRequestExpiry(
		authn.ContextWithIdentity(approverWriteSac, s.mockIdentity, s.T()),
		requestID,
		"update comment",
		expiry,
	)
	s.EqualError(err, fmt.Sprintf("request %s is not a deferral request thus doesn't have an expiry to update", req.GetId()))
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestUpdateRequestExpiryFailsIfRequestWasDenied() {
	expiry := &storage.RequestExpiry{Expiry: &storage.RequestExpiry_ExpiresWhenFixed{ExpiresWhenFixed: true}}
	requestID := uuid.NewTestUUID(1801).String()
	req := fixtures.GetGlobalDeferralRequest("cve-a-b-c").CloneVT()
	req.Status = storage.RequestStatus_DENIED
	req.Id = requestID
	req.Name = requestID

	s.injectRequest(req)

	_, err := s.datastore.UpdateRequestExpiry(
		authn.ContextWithIdentity(approverWriteSac, s.mockIdentity, s.T()),
		requestID,
		"update comment",
		expiry,
	)
	s.EqualError(err, fmt.Sprintf("request %s already expired or denied thus cannot be updated", req.GetId()))
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestUpdateRequestExpiryFailsIfRequestWasExpired() {
	expiry := &storage.RequestExpiry{Expiry: &storage.RequestExpiry_ExpiresWhenFixed{ExpiresWhenFixed: true}}
	requestID := uuid.NewTestUUID(1901).String()
	req := fixtures.GetGlobalDeferralRequest("cve-a-b-c").CloneVT()
	req.Expired = true
	req.Id = requestID
	req.Name = requestID

	s.injectRequest(req)

	_, err := s.datastore.UpdateRequestExpiry(
		authn.ContextWithIdentity(approverWriteSac, s.mockIdentity, s.T()),
		requestID,
		"update comment",
		expiry,
	)
	s.EqualError(err, fmt.Sprintf("request %s already expired or denied thus cannot be updated", req.GetId()))
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestUpdateRequestExpiryUpdatesExpiryIfRequestWasPending() {
	expiry := &storage.RequestExpiry{Expiry: &storage.RequestExpiry_ExpiresWhenFixed{ExpiresWhenFixed: true}}
	requestID := uuid.NewTestUUID(2001).String()
	req := fixtures.GetGlobalDeferralRequest("cve-a-b-c").CloneVT()
	req.Requestor = &storage.SlimUser{Id: fakeUserID}
	req.Status = storage.RequestStatus_PENDING
	req.Id = requestID
	req.Name = requestID

	s.injectRequest(req)

	resp, err := s.datastore.UpdateRequestExpiry(
		authn.ContextWithIdentity(requesterWriteSac, s.mockIdentity, s.T()),
		requestID,
		"update comment",
		expiry,
	)
	s.NoError(err)

	protoassert.Equal(s.T(), expiry, resp.GetDeferralReq().GetExpiry())
	s.Nilf(resp.GetUpdatedReq(), "updated field should be nil since original request was still pending")
	s.Equal(storage.RequestStatus_PENDING, resp.GetStatus())
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestUpdateRequestExpiryUpdatesExpiryIfRequestWasPendingUpdate() {
	expiry := &storage.RequestExpiry{Expiry: &storage.RequestExpiry_ExpiresWhenFixed{ExpiresWhenFixed: true}}
	requestID := uuid.NewTestUUID(2101).String()
	req := fixtures.GetGlobalDeferralRequest("cve-a-b-c").CloneVT()
	req.UpdatedReq = &storage.VulnerabilityRequest_UpdatedDeferralReq{UpdatedDeferralReq: req.GetDeferralReq().CloneVT()}
	req.Requestor = &storage.SlimUser{Id: fakeUserID}
	req.Status = storage.RequestStatus_APPROVED_PENDING_UPDATE
	req.Id = requestID
	req.Name = requestID

	s.injectRequest(req)

	resp, err := s.datastore.UpdateRequestExpiry(
		authn.ContextWithIdentity(requesterWriteSac, s.mockIdentity, s.T()),
		requestID,
		"update comment",
		expiry,
	)
	s.NoError(err)

	protoassert.Equal(s.T(), expiry, resp.GetUpdatedDeferralReq().GetExpiry())
	protoassert.Equal(s.T(), req.GetDeferralReq(), resp.GetDeferralReq(), "original request should not have been updated")
	protoassert.Equal(s.T(), req.GetFpRequest(), resp.GetFpRequest(), "original request should not have been updated")
	s.Equal(storage.RequestStatus_APPROVED_PENDING_UPDATE, resp.GetStatus())
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestUpdateRequestExpirySetsUpdatedIfOriginallyApproved() {
	expiry := &storage.RequestExpiry{Expiry: &storage.RequestExpiry_ExpiresWhenFixed{ExpiresWhenFixed: true}}
	requestID := uuid.NewTestUUID(2201).String()
	req := fixtures.GetGlobalDeferralRequest("cve-a-b-c")
	req.Requestor = &storage.SlimUser{Id: fakeUserID}
	req.Status = storage.RequestStatus_APPROVED
	req.Id = requestID
	req.Name = requestID

	s.injectRequest(req)

	resp, err := s.datastore.UpdateRequestExpiry(
		authn.ContextWithIdentity(requesterWriteSac, s.mockIdentity, s.T()),
		requestID,
		"update comment",
		expiry,
	)
	s.NoError(err)

	protoassert.Equal(s.T(), expiry, resp.GetUpdatedDeferralReq().GetExpiry())
	protoassert.Equal(s.T(), req.GetDeferralReq(), resp.GetDeferralReq(), "original request should not have been updated")
	protoassert.Equal(s.T(), req.GetFpRequest(), resp.GetFpRequest(), "original request should not have been updated")
	s.Equal(storage.RequestStatus_APPROVED_PENDING_UPDATE, resp.GetStatus())
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestUpdateRequestFailsIfRequestWasDenied() {
	update := &common.UpdateRequest{
		DeferralUpdate: &storage.DeferralUpdate{
			CVEs:   []string{"cve-1"},
			Expiry: &storage.RequestExpiry{Expiry: &storage.RequestExpiry_ExpiresWhenFixed{ExpiresWhenFixed: true}},
		},
	}

	requestID := uuid.NewTestUUID(2301).String()
	req := fixtures.GetGlobalDeferralRequestV2("cve-a-b-c").CloneVT()
	req.Status = storage.RequestStatus_DENIED
	req.Id = requestID
	req.Name = requestID

	s.injectRequest(req)

	_, err := s.datastore.UpdateRequest(
		authn.ContextWithIdentity(approverWriteSac, s.mockIdentity, s.T()),
		requestID,
		update,
	)
	s.EqualError(err, fmt.Sprintf("request %s cannot be updated because it has expired or has been denied", req.GetId()))
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestUpdateRequestFailsIfTypeIsDifferent() {
	// Test deferral update on false positive request.
	update := &common.UpdateRequest{
		DeferralUpdate: &storage.DeferralUpdate{
			CVEs:   []string{"cve-1"},
			Expiry: &storage.RequestExpiry{Expiry: &storage.RequestExpiry_ExpiresWhenFixed{ExpiresWhenFixed: true}},
		},
	}

	requestID := uuid.NewTestUUID(2401).String()
	req := fixtures.GetGlobalFPRequestV2("cve-a-b-c").CloneVT()
	req.Status = storage.RequestStatus_APPROVED
	req.Id = requestID
	req.Name = requestID

	s.injectRequest(req)

	_, err := s.datastore.UpdateRequest(
		authn.ContextWithIdentity(approverWriteSac, s.mockIdentity, s.T()),
		requestID,
		update,
	)
	s.EqualError(err, fmt.Sprintf("exception %s cannot be updated. Exception type(defer/false positive) cannot be changed", req.GetId()))

	// Test false positive update on deferral request.
	update = &common.UpdateRequest{
		FalsePositiveUpdate: &storage.FalsePositiveUpdate{
			CVEs: []string{"cve-1"},
		},
	}

	requestID = uuid.NewTestUUID(2402).String()
	req = fixtures.GetGlobalDeferralRequestV2("cve-a-b-c").CloneVT()
	req.Status = storage.RequestStatus_APPROVED
	req.Id = requestID
	req.Name = requestID

	s.injectRequest(req)

	_, err = s.datastore.UpdateRequest(
		authn.ContextWithIdentity(approverWriteSac, s.mockIdentity, s.T()),
		requestID,
		update,
	)
	s.EqualError(err, fmt.Sprintf("exception %s cannot be updated. Exception type(defer/false positive) cannot be changed", req.GetId()))

}

func (s *VulnRequestPostgresDataStoreTestSuite) TestUpdateRequestFailsIfNoOp() {
	// Test deferral update on false positive request.
	update := &common.UpdateRequest{
		DeferralUpdate: &storage.DeferralUpdate{
			CVEs:   []string{"cve-1"},
			Expiry: &storage.RequestExpiry{Expiry: &storage.RequestExpiry_ExpiresWhenFixed{ExpiresWhenFixed: true}},
		},
	}

	requestID := uuid.NewTestUUID(2501).String()
	req := fixtures.GetGlobalDeferralRequestV2("cve-1").CloneVT()
	req.Status = storage.RequestStatus_APPROVED
	req.GetDeferralReq().Expiry = update.DeferralUpdate.GetExpiry().CloneVT()
	req.Id = requestID
	req.Name = requestID

	s.injectRequest(req)

	_, err := s.datastore.UpdateRequest(
		authn.ContextWithIdentity(approverWriteSac, s.mockIdentity, s.T()),
		requestID,
		update,
	)
	s.EqualError(err, fmt.Sprintf("the update does not change the exception %s", req.GetId()))

	// Test false positive update on deferral request.
	update = &common.UpdateRequest{
		FalsePositiveUpdate: &storage.FalsePositiveUpdate{
			CVEs: []string{"cve-1"},
		},
	}

	requestID = uuid.NewTestUUID(2502).String()
	req = fixtures.GetGlobalFPRequestV2("cve-1").CloneVT()
	req.Status = storage.RequestStatus_APPROVED
	req.Id = requestID
	req.Name = requestID

	s.injectRequest(req)

	_, err = s.datastore.UpdateRequest(
		authn.ContextWithIdentity(approverWriteSac, s.mockIdentity, s.T()),
		requestID,
		update,
	)
	s.EqualError(err, fmt.Sprintf("the update does not change the exception %s", req.GetId()))
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestUpdateRequestFailsIfRequestWasExpired() {
	update := &common.UpdateRequest{
		DeferralUpdate: &storage.DeferralUpdate{
			CVEs:   []string{"cve-1"},
			Expiry: &storage.RequestExpiry{Expiry: &storage.RequestExpiry_ExpiresWhenFixed{ExpiresWhenFixed: true}},
		},
	}
	requestID := uuid.NewTestUUID(2601).String()
	req := fixtures.GetGlobalDeferralRequestV2("cve-a-b-c").CloneVT()
	req.Expired = true
	req.Id = requestID
	req.Name = requestID

	s.injectRequest(req)

	_, err := s.datastore.UpdateRequest(
		authn.ContextWithIdentity(approverWriteSac, s.mockIdentity, s.T()),
		requestID,
		update,
	)
	s.EqualError(err, fmt.Sprintf("request %s cannot be updated because it has expired or has been denied", req.GetId()))
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestUpdateRequestSucceedsIfDeferralRequestWasPending() {
	update := &common.UpdateRequest{
		DeferralUpdate: &storage.DeferralUpdate{
			CVEs:   []string{"cve-1"},
			Expiry: &storage.RequestExpiry{Expiry: &storage.RequestExpiry_ExpiresWhenFixed{ExpiresWhenFixed: true}},
		},
	}
	requestID := uuid.NewTestUUID(2701).String()
	req := fixtures.GetGlobalDeferralRequestV2("cve-a-b-c").CloneVT()
	req.Requestor = &storage.SlimUser{Id: fakeUserID}
	req.Status = storage.RequestStatus_PENDING
	req.Id = requestID
	req.Name = requestID

	s.injectRequest(req)

	resp, err := s.datastore.UpdateRequest(
		authn.ContextWithIdentity(requesterWriteSac, s.mockIdentity, s.T()),
		requestID,
		update,
	)
	s.NoError(err)

	protoassert.Equal(s.T(), update.DeferralUpdate.GetExpiry(), resp.GetDeferralReq().GetExpiry())
	s.Equal(update.DeferralUpdate.GetCVEs(), resp.GetCves().GetCves())
	s.Nil(resp.GetUpdatedReq())
	s.Equal(storage.RequestStatus_PENDING, resp.GetStatus())
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestUpdateRequestSucceedsIfDeferralUpdateWasPending() {
	update := &common.UpdateRequest{
		DeferralUpdate: &storage.DeferralUpdate{
			CVEs:   []string{"cve-1"},
			Expiry: &storage.RequestExpiry{Expiry: &storage.RequestExpiry_ExpiresWhenFixed{ExpiresWhenFixed: true}},
		},
	}
	requestID := uuid.NewTestUUID(2801).String()
	req := fixtures.GetGlobalDeferralRequestV2("cve-a-b-c")
	req.UpdatedReq = &storage.VulnerabilityRequest_UpdatedDeferralReq{UpdatedDeferralReq: req.GetDeferralReq().CloneVT()}
	req.Requestor = &storage.SlimUser{Id: fakeUserID}
	req.Status = storage.RequestStatus_APPROVED_PENDING_UPDATE
	req.Id = requestID
	req.Name = requestID

	s.injectRequest(req)

	resp, err := s.datastore.UpdateRequest(
		authn.ContextWithIdentity(requesterWriteSac, s.mockIdentity, s.T()),
		requestID,
		update,
	)
	s.NoError(err)

	protoassert.Equal(s.T(), update.DeferralUpdate, resp.GetDeferralUpdate())
	s.Equal([]string{"cve-a-b-c"}, resp.GetCves().GetCves())
	s.Equal(storage.RequestStatus_APPROVED_PENDING_UPDATE, resp.GetStatus())
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestUpdateRequestSucceedsIfOriginalDeferralReqApproved() {
	update := &common.UpdateRequest{
		DeferralUpdate: &storage.DeferralUpdate{
			CVEs: []string{"cve-1"},
		},
	}
	requestID := uuid.NewTestUUID(2901).String()
	req := fixtures.GetGlobalDeferralRequestV2("cve-a-b-c").CloneVT()
	req.Requestor = &storage.SlimUser{Id: fakeUserID}
	req.Status = storage.RequestStatus_APPROVED
	req.Id = requestID
	req.Name = requestID

	s.injectRequest(req)

	resp, err := s.datastore.UpdateRequest(
		authn.ContextWithIdentity(requesterWriteSac, s.mockIdentity, s.T()),
		requestID,
		update,
	)
	s.NoError(err)

	protoassert.Equal(s.T(), req.GetFalsePositiveUpdate(), resp.GetFalsePositiveUpdate())
	s.Equal([]string{"cve-a-b-c"}, req.GetCves().GetCves())
	s.Equal(storage.RequestStatus_APPROVED_PENDING_UPDATE, resp.GetStatus())
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestUpdateRequestSucceedsIfOriginalFPReqApproved() {
	update := &common.UpdateRequest{
		DeferralUpdate: &storage.DeferralUpdate{
			CVEs:   []string{"cve-1"},
			Expiry: &storage.RequestExpiry{Expiry: &storage.RequestExpiry_ExpiresWhenFixed{ExpiresWhenFixed: true}},
		},
	}
	requestID := uuid.NewTestUUID(3001).String()
	req := fixtures.GetGlobalDeferralRequestV2("cve-a-b-c").CloneVT()
	req.Requestor = &storage.SlimUser{Id: fakeUserID}
	req.Status = storage.RequestStatus_APPROVED
	req.Id = requestID
	req.Name = requestID

	s.injectRequest(req)

	resp, err := s.datastore.UpdateRequest(
		authn.ContextWithIdentity(requesterWriteSac, s.mockIdentity, s.T()),
		requestID,
		update,
	)
	s.NoError(err)

	protoassert.Equal(s.T(), update.DeferralUpdate, resp.GetDeferralUpdate())
	s.Equal([]string{"cve-a-b-c"}, req.GetCves().GetCves())
	s.Equal(storage.RequestStatus_APPROVED_PENDING_UPDATE, resp.GetStatus())
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestMarkRequestInactiveRequiresWriteOnAny() {
	for ix, ctx := range []context.Context{requesterWriteSac, requesterAllSac, approverWriteSac, approverAllSac, selfApproverWriteSac, selfApproverAllSac} {
		requestID := uuid.NewTestUUID(ix + 3101).String()
		s.injectGeneratedRequest(requestID)
		_, err := s.datastore.MarkRequestInactive(
			authn.ContextWithIdentity(ctx, s.mockIdentity, s.T()),
			requestID,
			"comment",
		)
		s.NoError(err)
	}

	for ix, ctx := range []context.Context{requesterReadSac, approverReadSac, selfApproverReadSac, noVMAccessSac} {
		requestID := uuid.NewTestUUID(ix + 3111).String()
		s.injectGeneratedRequest(requestID)
		_, err := s.datastore.MarkRequestInactive(ctx, requestID, "comment")
		s.ErrorIs(err, sac.ErrResourceAccessDenied)
	}
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestRequesterCannotMarkOthersRequestInactive() {
	for ix, ctx := range []context.Context{requesterWriteSac, requesterAllSac} {
		requestID := uuid.NewTestUUID(ix + 3201).String()
		s.injectGeneratedRequest(requestID)
		_, err := s.datastore.MarkRequestInactive(
			authn.ContextWithIdentity(ctx, s.altIdentity, s.T()),
			requestID,
			"comment",
		)
		s.ErrorIs(err, sac.ErrResourceAccessDenied)
	}
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestApproversCanMarkOthersRequestInactive() {
	for ix, ctx := range []context.Context{approverWriteSac, approverAllSac, selfApproverWriteSac, selfApproverAllSac} {
		requestID := uuid.NewTestUUID(ix + 3301).String()
		s.injectGeneratedRequest(requestID)
		_, err := s.datastore.MarkRequestInactive(
			authn.ContextWithIdentity(ctx, s.altIdentity, s.T()),
			requestID,
			"comment",
		)
		s.NoError(err)
	}
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestMarkRequestInactiveFailsWhenAlreadyInactive() {
	for ix, ctx := range []context.Context{requesterWriteSac, requesterAllSac, approverWriteSac, approverAllSac, selfApproverWriteSac, selfApproverAllSac} {
		requestID := uuid.NewTestUUID(ix + 3401).String()
		s.injectGeneratedExpiredRequest(requestID)
		_, err := s.datastore.MarkRequestInactive(
			authn.ContextWithIdentity(ctx, s.mockIdentity, s.T()),
			requestID,
			"comment",
		)
		expectedErrorString := fmt.Sprintf("vulnerability request %s has expired. Undo is noop", requestID)
		s.EqualError(err, expectedErrorString)
	}
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestMarkRequestInactiveSetsComment() {
	requestID := uuid.NewTestUUID(3501).String()
	s.injectGeneratedRequest(requestID)
	resp, err := s.datastore.MarkRequestInactive(
		authn.ContextWithIdentity(selfApproverAllSac, s.mockIdentity, s.T()),
		requestID,
		"this is a comment",
	)
	s.NoError(err)
	s.Len(resp.GetComments(), 1)
	s.Equal(resp.GetComments()[0].GetMessage(), "this is a comment")
	s.Equal(resp.GetComments()[0].GetUser().GetName(), s.mockIdentity.FullName())
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestOnlyRequesterWithWriteCanRemoveOwnRequest() {
	for ix, ctx := range []context.Context{requesterWriteSac, requesterAllSac, selfApproverWriteSac, selfApproverAllSac} {
		requestID := uuid.NewTestUUID(ix + 3601).String()
		s.injectGeneratedRequest(requestID)
		err := s.datastore.RemoveRequest(
			authn.ContextWithIdentity(ctx, s.mockIdentity, s.T()),
			requestID,
		)
		s.NoError(err)
		rsp, found, err := s.datastore.Get(selfApproverAllSac, requestID)
		s.NoError(err)
		s.False(found)
		s.Nil(rsp)
	}

	for ix, ctx := range []context.Context{requesterReadSac, approverReadSac, approverWriteSac, approverAllSac, selfApproverReadSac, noVMAccessSac} {
		requestID := uuid.NewTestUUID(ix + 3611).String()
		req := createPendingVulnerabilityRequest(requestID)
		s.injectRequest(req)
		err := s.datastore.RemoveRequest(ctx, requestID)
		s.ErrorIs(err, sac.ErrResourceAccessDenied)
		rsp, found, err := s.datastore.Get(selfApproverAllSac, requestID)
		s.NoError(err)
		s.True(found)
		protoassert.Equal(s.T(), req, rsp)
	}
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestOnlyRequesterWithWriteCannotRemoveOthersRequests() {
	for ix, ctx := range []context.Context{requesterWriteSac, requesterAllSac, selfApproverWriteSac, selfApproverAllSac} {
		requestID := uuid.NewTestUUID(ix + 3701).String()
		req := createPendingVulnerabilityRequest(requestID)
		s.injectRequest(req)
		err := s.datastore.RemoveRequest(
			authn.ContextWithIdentity(ctx, s.altIdentity, s.T()),
			requestID,
		)
		s.ErrorIs(err, sac.ErrResourceAccessDenied)
		rsp, found, err := s.datastore.Get(selfApproverAllSac, requestID)
		s.NoError(err)
		s.True(found)
		protoassert.Equal(s.T(), req, rsp)
	}
	for ix, ctx := range []context.Context{requesterWriteSac, requesterAllSac, selfApproverWriteSac, selfApproverAllSac} {
		requestID := uuid.NewTestUUID(ix + 3711).String()
		req := createPendingVulnerabilityRequest(requestID)
		s.injectRequest(req)
		err := s.datastore.RemoveRequest(
			authn.ContextWithIdentity(ctx, s.mockIdentity, s.T()),
			requestID,
		)
		s.NoError(err)
		rsp, found, err := s.datastore.Get(selfApproverAllSac, requestID)
		s.NoError(err)
		s.False(found)
		s.Nil(rsp)
	}
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestRemoveRequestPending() {
	requestID := uuid.NewTestUUID(3801).String()
	req := createPendingVulnerabilityRequest(requestID)
	req.Status = storage.RequestStatus_PENDING
	req.UpdatedReq = &storage.VulnerabilityRequest_UpdatedDeferralReq{}

	s.injectRequest(req)
	err := s.datastore.RemoveRequest(
		authn.ContextWithIdentity(selfApproverAllSac, s.mockIdentity, s.T()),
		requestID,
	)
	s.NoError(err)
	rsp, found, err := s.datastore.Get(selfApproverAllSac, requestID)
	s.NoError(err)
	s.False(found)
	s.Nil(rsp)
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestRemoveRequestPendingUpdate() {
	requestID := uuid.NewTestUUID(3901).String()
	req := createPendingVulnerabilityRequest(requestID)
	req.Status = storage.RequestStatus_APPROVED_PENDING_UPDATE
	req.UpdatedReq = &storage.VulnerabilityRequest_UpdatedDeferralReq{}
	s.injectRequest(req)

	err := s.datastore.RemoveRequest(
		authn.ContextWithIdentity(selfApproverAllSac, s.mockIdentity, s.T()),
		requestID,
	)
	s.NoError(err)

	rsp, found, err := s.datastore.Get(selfApproverAllSac, requestID)
	s.NoError(err)
	s.True(found)
	s.Equal(storage.RequestStatus_APPROVED, rsp.GetStatus())
	s.Nil(rsp.GetUpdatedReq())
}

func (s *VulnRequestPostgresDataStoreTestSuite) TestRemoveRequestApproved() {
	requestID := uuid.NewTestUUID(4001).String()
	req := createPendingVulnerabilityRequest(requestID)
	req.Status = storage.RequestStatus_APPROVED
	req.UpdatedReq = &storage.VulnerabilityRequest_UpdatedDeferralReq{}
	s.injectRequest(req)

	err := s.datastore.RemoveRequest(
		authn.ContextWithIdentity(selfApproverAllSac, s.mockIdentity, s.T()),
		requestID,
	)
	s.Error(err)

	rsp, found, err := s.datastore.Get(selfApproverAllSac, requestID)
	s.NoError(err)
	s.True(found)
	protoassert.Equal(s.T(), req, rsp)
}
